const inquirer = require('inquirer')
const fs = require('fs')
const cmd = require('child_process')
const utils = require('./utils')
const ora = require('ora')
let loading = ora()

// child_process.exec 所需的参数，避免 maxBuffer 不足而导致错误
const execOption = {
        encoding: 'utf8',
        timeout: 0,
        maxBuffer: 1000 * 1024 * 1024, // 默认 200 * 1024
        killSignal: 'SIGTERM'
    }

/*
 * 编译项目，合并 framework
 */
async function framework() {
    try {
        let startTime = new Date().getTime()

        let target = await getTarget()
        let answer = await initParam(target)
        await buildAction(answer.target, answer.configuration, 'iphoneos')
        await buildAction(answer.target, answer.configuration, 'iphonesimulator')
        await mergeAction(answer.target, answer.configuration, answer.mergePath)

        let endTime = new Date().getTime()
        utils.printLog(`总耗时：[${(endTime-startTime)/1000} sec]`)
    } catch (error) {
        console.log(error)
    }
}

/**
 * 1、从当前路径下读取基本信息，获取 target
 */
function getTarget() {
    return new Promise((resolve, reject) => {
        fs.readdir(process.cwd(), (err, files) => {
            if (err) {
                console.log(err)
                reject(err)
            }
            let target = null
            files.forEach(file => {
                if (file.includes('.xcworkspace')) {
                    target = file.split('.')[0]
                    return
                }
                if (file.includes('.xcodeproj')) {
                    target = file.split('.')[0]
                }
            })
            resolve(target)
        })
    })
}

function initParam(target) {
    const promptList = [
        {
            type: 'input',
            name: 'target',
            message: '项目 Target 名字？',
            default: target
        },
        {
            type: 'list',
            name: 'configuration',
            message: '编译的环境?',
            choices: [
                'Debug',
                'Release'
            ]
        },
        {
            type: 'input',
            name: 'mergePath',
            message: '合并后 framework 存放路径？',
            default: './Framework'
        }
    ]
    return new Promise((resolve, reject) => {
        inquirer.prompt(promptList)
            .then(answer => {
                resolve(answer)
            })
    })
}

/*
 * 编译
 */
function buildAction(target, configuration, sdk) {
    loading.text = `build ${target} ${sdk}...`
    loading.start()
    let build_cmd = `xcodebuild build -target ${target} ONLY_ACTIVE_ARCH=NO -configuration ${configuration} -sdk ${sdk}`
    return new Promise((resolve, reject) => {
        cmd.exec(build_cmd, execOption, (err, stdout) => {
            loading.stop()
            if (err) {
                return reject(err)
            }
            utils.printSuccessLog(`build ${target} ${sdk} succeeded`)
            resolve()
        })
    })
}

/*
 * 合并 framework 
 * 
 * lipo -create 命令会在当前项目路径下，创建一个 build 文件夹，存在编译产物
 */
function mergeAction(target, configuration, mergePath) {
    let projectPath = process.cwd()
    // 输出 framework 路径
    let outputFrameworkPath = mergePath
    // 输出文件路径
    let outputFilePath = `${outputFrameworkPath}/${target}.framework/${target}`
    // 模拟器 framework 路径
    let simulatorFrameworkPath = `${projectPath}/build/${configuration}-iphonesimulator/${target}.framework`
    // 模拟器待合并文件路径
    let simulatorFilePath = `${simulatorFrameworkPath}/${target}`
    // 真机 framework 路径
    let iphoneosFrameworkPath = `${projectPath}/build/${configuration}-iphoneos/${target}.framework`
    // 真机待合并文件路径
    let iphoneosFilePath = `${iphoneosFrameworkPath}/${target}`
    // 合并命令
    let merge_cmd = `lipo -create ${simulatorFilePath} ${iphoneosFilePath} -output ${outputFilePath}`

    // 创建 output 路径
    let exist = fs.existsSync(outputFrameworkPath)
    if (!exist) {
        fs.mkdirSync(outputFrameworkPath, {recursive: true})
    }
    // 复制一份 framework 到 output 
    cmd.execSync(`cp -r ${iphoneosFrameworkPath} ${outputFrameworkPath}`)

    loading.text = 'merge...'
    loading.start()
    // 合并产物替换输出路径中存在的 framework 文件
    return new Promise((resolve, reject) => {
        cmd.exec(merge_cmd, execOption, (err, stdout) => {
            loading.stop()
            if (err) {
                return reject(err)
            }
            utils.printSuccessLog(`merge succeeded`)
            resolve()
            // 删除中间产物 build
            cmd.execSync(`rm -r ${projectPath}/build`)
            utils.printSuccessLog(`delete ${projectPath}/build succeeded`)
        })
    })
}

module.exports = framework;